home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / i_set.exe / I-SET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-04  |  19.7 KB  |  761 lines

  1. /* I-SET.c ****************************************************************
  2. A very simple module to allow modification of master
  3. environment under DOS.
  4. External entry points:
  5.  
  6. int iset_load_envstrings (BYTEPTR envblock, char *envstrings[], unsigned *pused)
  7.     Loads the enviromnment in an array of char *. Each entry
  8.     is malloc'd by the function, so it is expected that
  9.     iset_free_envstrings is called after use.
  10.     This routine was originally internal (used by others in this module)
  11.     but it is now public should anyone care. No checking on array
  12.     dimensions!
  13.     If pfree is not NULL, the functions fills it with the number of
  14.     bytes currently used in the environment
  15.  
  16. int iset_free_envstrings (char *envstrings[])
  17.     Frees the copy alloc'd by iset_load_envstrings. It is expected
  18.     that the last valid entry in the array is a zero-length string
  19.     (iset_load_envstrings does this).
  20.  
  21. char *iset_getenv (char *env_par)
  22.     Just like getenv(), only this works on the original environment.
  23.     After use of other functions in this module, the copy which
  24.     is accessed by getenv() could be out of date in respect of
  25.     the master. Used internally also.
  26.  
  27. int iset_set_string (char *env_par, char *env_value)
  28.     Actually a setenv() on the master environment. If a string
  29.     with env_par isn't found, it is added to the environment.
  30.     If env_value is NULL, the string is addedd just like UNIX.
  31.     Note that this routine does attempt to get the strlen()
  32.     of a NULL: in MSC 6.0, the result is 0 and no problem.
  33.     Please look out in other cases.
  34.  
  35. int    iset_append_to_string (char *env_par, char *env_value, int before)
  36.     Adds a new env_value to the end or the beginning
  37.     of the actual value of an environment string, depending
  38.     on before (0: append; 1: insert before).
  39.     If the string didn't exist, it falls
  40.     back to iset_set_string. Otherwise, the string is appended
  41.     with a preceding semi-colon.
  42.  
  43. int iset_cut_string (char *env_par, char *string_to_cut)
  44.     The opposite of iset_append_string. If a string with name
  45.     env_par is found, string_to_cut is searched between pairs
  46.     of semicolons and, if found, the original string is collapsed
  47.     to exclude it. If the string isn't found nothing is done.
  48.  
  49. int iset_delete_string (char *env_par)
  50.     Remove the identified string from the environment. This works
  51.     also on no-value strings which can be produced by
  52.     iset_set_string.
  53.  
  54. int    iset_show_strings (void)
  55.     Will output on stdout the contents of the master environment
  56.     and (little) additional statistics. Useful for seeing variables
  57.     longer than 127 chars, which DOS's set will truncate to 127.
  58.  
  59. This module has been extensively used. Still we don't expect it to
  60. work in every situation! Do complete testings because alteration
  61. of master environment can produce tricky situations to debug.
  62. You can use this source as you like provided you leave this notes
  63. in the module together with the variable id.
  64. Please note that, to assure reentrancy, all functions load a complete
  65. array of pointers (dimension is hardwired) so stack space might
  66. be an issue.
  67.  
  68. I-SET was written by Shari (Davide Migliavacca) of Inferentia S.r.l.,
  69. via Venezian 10, 20123 Milano ITALY.
  70. Tel. +39.2.266680568.
  71. CompuServe 100016,2335
  72. **********************************************************/
  73.  
  74. /* You can't remove this lines */
  75. #define VERSIONE    "3.53"
  76. static const char *id= "I-Set " VERSIONE " " __DATE__ " " __TIME__ " Created by Shari CIS 100016,2335";
  77. /*******************************/
  78.  
  79.  
  80.  
  81. #include <stdio.h>
  82. #include <stdlib.h>
  83. #include <string.h>
  84. #include <dos.h>
  85. #include <options.h>
  86.  
  87.  
  88. /* Should DOS grow beyond this limit, you may put
  89.    a version checking function instead of this macro */
  90. #define dos_max_pathvar_length()    127
  91. int    iset_check_length(char *env_par, int len);
  92.  
  93.  
  94. typedef unsigned char BYTE;
  95. typedef unsigned int WORD;
  96. typedef unsigned long DWORD;
  97. typedef BYTE _far * BYTEPTR;
  98. typedef WORD _far * WORDPTR;
  99. typedef DWORD _far *DWORDPTR;
  100. typedef void _far *FP;
  101.  
  102.  
  103.  
  104. #define MK_FP(seg, off)        ((FP)((DWORD)(((WORD)(off)) | ((DWORD)((WORD)(seg))) << 16 )))
  105.  
  106. #define    INT20h    0xCD20
  107.  
  108. static char terminating_null = '\0';
  109. union REGS regs;
  110.  
  111. typedef struct tagPSP {
  112.     WORD        int20;            /* must be 0xCD20 */
  113.     WORD        alloc_end_seg;        /* segment, end of allocation block */
  114.     BYTE        reserved_1;        
  115.     BYTE        far_call;            /* call far ... next field */
  116.     DWORD    DOS_dispatcher;    /* address of DOS dispatcher */
  117.     DWORD    termination_handler;/* int 22h contents */
  118.     DWORD    ctrl_c_handler;    /* int 23h contents */
  119.     DWORD    crit_err_handler;    /* int 24h contents */
  120.     WORD        parent_PSP;        /* UNDOCUMENTED */
  121.     BYTE        JFT[20];            /* Job file table: UNDOCUMENTED */
  122.     WORD        env_seg;            /* segment of environment block */
  123.     DWORD    reserved_2;        
  124.     WORD        max_opens;        /* # of entries in JFT: UNDOCUMENTED */
  125.     DWORD    actual_JFT;        /* Address of actual JFT: UNDOCUMENTED */
  126.     BYTE        reserved_3[36];
  127.     BYTE        FCB_1[16];        /* Default FCB #1 */
  128.     BYTE        FCB_2[20];        /* Default FCB #2 (overlaid by 1 if used)*/
  129.     BYTE        command_tail[128];    /* command tail and DTA */
  130. } PSP;
  131.  
  132.  
  133. typedef struct tagMCB {
  134.     BYTE        type;
  135.     WORD        owner;    /* PSP of owner */
  136.     WORD        size;
  137.     BYTE        reserved[3];
  138.     BYTE        dos4[8];
  139. } MCB;
  140.  
  141.  
  142. static unsigned env_size(WORD envseg)
  143. {
  144.     unsigned envsize;
  145. _asm {
  146.         mov    ax,envseg             /* get segment of env */
  147.         dec    ax                  /* back up to MCB */
  148.         mov    es,ax
  149.         mov    ax,es:[0003h]       /* get size in grafs */
  150.         mov    envsize, ax
  151.     }
  152.     return envsize << 4;        /* multiply by paragraph size */
  153. }
  154.  
  155.  
  156. /* determines if seg is really a psp:
  157.     1)    at seg-1 there must be a DOS MCB whose owner is seg
  158.     2)    the first two bytes in seg must be 0xCD 0x20 (int 20h)
  159.   From "Undocumented DOS" by Andrew Schulman, Byte  Vol. 16, #3 (March 1991)
  160. */
  161. static int is_psp (WORD seg)
  162. {
  163.     return ((((MCB _far *) MK_FP(seg-1, 0))->owner == seg) &&
  164.            (*((WORD _far *) MK_FP(seg, 0)) == INT20h));
  165. }
  166.  
  167.  
  168. static WORD get_shell_psp_seg()
  169. {
  170.     PSP    _far *my_psp;
  171.     PSP    _far *parent_psp;
  172.  
  173.     /* get PSP address (int 21h fun 62h, DOS >= 3.0) */
  174.  
  175.     regs.h.ah = 0x62;
  176.  
  177.     intdos (®s, ®s);
  178.     
  179.     /* bx contains segment of PSP */
  180.  
  181.     my_psp = (PSP _far *)MK_FP(regs.x.bx, 0);
  182.  
  183.     do {
  184.         parent_psp = (PSP _far *)MK_FP(my_psp->parent_PSP, 0);
  185.         my_psp = parent_psp;
  186.     } while (parent_psp->parent_PSP != FP_SEG(parent_psp));
  187.  
  188.  
  189.     return FP_SEG(parent_psp);
  190.  
  191. static BYTEPTR get_envblock ()
  192. {
  193.     WORD    shell_psp_seg;
  194.     PSP _far *shell_psp;
  195.  
  196.     shell_psp_seg = get_shell_psp_seg();
  197.     shell_psp = (PSP _far *) MK_FP(shell_psp_seg, 0);
  198.  
  199.     return ((BYTEPTR) MK_FP(shell_psp->env_seg, 0));
  200. }
  201.  
  202. int iset_load_envstrings (BYTEPTR envblock, char *envstrings[], unsigned *pused)
  203. {
  204.     char _far *envpointer = (char _far *)envblock;
  205.     size_t len;
  206.     int    i = 0;
  207.  
  208.     while (*envpointer != '\0') {
  209.         len = _fstrlen (envpointer);
  210.         envstrings[i] = (char *) malloc (len + 1);
  211.         _fstrcpy ((char _far *) envstrings[i], envpointer);
  212.         envpointer += (len + 1);
  213.         ++i;
  214.     }
  215.     envstrings[i] = &terminating_null;
  216.     if (pused != (unsigned *)NULL)
  217.         *pused = (unsigned) (envpointer - envblock);
  218.  
  219.     return i;
  220. }
  221.  
  222. int iset_free_envstrings (char *envstrings[])
  223. {
  224.     int i = 0;
  225.  
  226.     while (envstrings[i][0] != '\0')
  227.         free (envstrings[i++]);
  228.  
  229.     return 0;
  230. }
  231.  
  232.     
  233. static int    search_string (char *string, char *array[])
  234. {
  235.     int i = 0;
  236.  
  237.     while (array[i][0] != '\0')
  238.     {
  239.         if (!strnicmp(array[i], string, strlen(string)))
  240.             return i;
  241.         else
  242.             i++;
  243.     }
  244.  
  245.     return -1;
  246. }
  247.  
  248.  
  249. /* works on original environment, which may be different
  250.    from our copy because of other iset_... function calls */
  251. char *iset_getenv (char *env_par)
  252. {
  253.     char *env_strings[128];
  254.     BYTEPTR    envblock;
  255.     int    maxstring;
  256.     int    i;
  257.     static char env_name[128];
  258.     static char env_value[256];
  259.     char    *return_this = NULL;
  260.     char    *equal;
  261.  
  262.     envblock = get_envblock();
  263.     maxstring = iset_load_envstrings (envblock, env_strings, NULL);
  264.  
  265.     env_value[0] = '\0';
  266.     for (i = 0; i < maxstring; i++) {
  267.         equal = strchr(env_strings[i], '=');
  268.         if (equal != NULL) {
  269.             strncpy (env_name, env_strings[i], equal - env_strings[i]);
  270.             env_name[equal - env_strings[i]]='\0';
  271.         }
  272.         else
  273.             strcpy (env_name, env_strings[i]);
  274.         if (!stricmp(env_name, env_par)) {
  275.             /* return value */
  276.             if (equal==NULL)
  277.                 env_value[0] = '\0';
  278.             else
  279.                 strcpy (env_value, ++equal);
  280.             return_this = env_value;
  281.             break;
  282.         }
  283.     }
  284.  
  285.  
  286.     iset_free_envstrings(env_strings);
  287.     return return_this;
  288. }
  289.     
  290.  
  291. int iset_delete_string (char *env_par)
  292. {
  293.     char *env_strings[128];
  294.     char *new_string;
  295.     BYTEPTR    envblock;
  296.     int    maxstring;
  297.     int    i;
  298.     int    this_one;
  299.     int    len;
  300.  
  301.     envblock = get_envblock();
  302.     maxstring = iset_load_envstrings (envblock, env_strings, NULL);
  303.  
  304.     if ((this_one = search_string(env_par, env_strings)) == -1)
  305.     {
  306.         /* string not found  - quietly exit */
  307.         return 1;
  308.     }
  309.  
  310.  
  311.     /* throw away old string */
  312.     new_string = env_strings[this_one];
  313.     free (new_string);
  314.     for (i = this_one; i < maxstring; i++)
  315.         env_strings[i] = env_strings[i + 1];
  316.     maxstring--;
  317.  
  318.     /* rebuild environment block */
  319.     for (i = 0; i <= maxstring; i++) {
  320.         len = strlen (env_strings[i]) + 1; /* copy null byte */
  321.         _fmemcpy(envblock, (void _far *)env_strings[i], len);
  322.         envblock += len;
  323.     }
  324.  
  325.     *envblock = '\0';
  326.  
  327.     iset_free_envstrings(env_strings);
  328.     return 0;
  329. }
  330.  
  331.  
  332. int iset_set_string (char *env_par, char *env_value)
  333. {
  334.     char *env_strings[128];
  335.     char *new_string;
  336.     BYTEPTR    envblock;
  337.     unsigned    envused;
  338.     unsigned    envfree;
  339.     int    maxstring;
  340.     int    i;
  341.     int    this_one;
  342.     int    len;
  343.     int    ret;
  344.  
  345.     if (iset_check_length(env_par, strlen(env_value) + strlen(env_par) + 2) !=0) {
  346.         return 1;
  347.     }
  348.  
  349.     envblock = get_envblock();
  350.     maxstring = iset_load_envstrings (envblock, env_strings, &envused);
  351.     envfree = env_size(FP_SEG(envblock)) - envused;
  352.  
  353.     if ((this_one = search_string(env_par, env_strings)) != -1)
  354.     {
  355. #ifdef ISETDEBUG
  356.         fprintf(stderr, "[D] Found existing %s\", env_strings[this_one]);
  357. #endif
  358.         /* throw away old string and add at the end */
  359.         new_string = env_strings[this_one];
  360.         envfree += (strlen(new_string) + 1);
  361.         free (new_string);
  362.         for (i = this_one; i < maxstring; i++)
  363.             env_strings[i] = env_strings[i + 1];
  364.         maxstring--;
  365.     }
  366.  
  367.     new_string = (char *)malloc (strlen(env_par) + strlen(env_value) + 2);
  368.  
  369.     if (env_value != NULL)
  370.         sprintf(new_string, "%s=%s", strupr(env_par), env_value);
  371.     else
  372.         strcpy (new_string, strupr (env_par));
  373.  
  374.     if (strlen(new_string) + 1 <= envfree)
  375.     {
  376.         env_strings[maxstring] = new_string;
  377.         ++maxstring;
  378.         env_strings[maxstring] = &terminating_null;
  379.  
  380.         /* rebuild environment block */
  381.  
  382.  
  383.         for (i = 0; i <= maxstring; i++) {
  384.             len = strlen (env_strings[i]) + 1; /* copy null byte */
  385.             _fmemcpy(envblock, (void _far *)env_strings[i], len);
  386.             envblock += len;
  387.         }
  388.  
  389.         *envblock = '\0';
  390.         ret = 0;
  391.     }
  392.     else
  393.         ret = 2;
  394.     iset_free_envstrings(env_strings);
  395.  
  396.     return ret;
  397. }
  398.  
  399. int    iset_append_to_string (char *env_par, char *env_value, int before)
  400. {
  401.     char        *env_strings[128];
  402.     register    char    *new_string;
  403.     char        *equal_sign;
  404.     BYTEPTR    envblock;
  405.     unsigned    envused;
  406.     unsigned    envfree;
  407.     int        maxstring;
  408.     int        i;
  409.     int        this_one;
  410.     int        len;
  411.     int        newlen;
  412.     int        ret;
  413.  
  414.     envblock = get_envblock();
  415.     maxstring = iset_load_envstrings (envblock, env_strings, &envused);
  416.     envfree = env_size(FP_SEG(envblock)) - envused;
  417.     if ((this_one = search_string(env_par, env_strings)) != -1)
  418.     {
  419. #ifdef ISETDEBUG
  420.         fprintf(stderr, "[D] Found existing %s\", env_strings[this_one]);
  421. #endif
  422.         /* append value to beginning of old string suffixing with a ; */
  423.         len = strlen(env_strings[this_one]) + strlen (env_value) + 2;    /* ; and  nul */
  424.         /* check existence of '=' in string. using iset_set_string
  425.            it is possible to create an assert-only var a la Unix. Now
  426.            we have to complete that. */
  427.         equal_sign = strchr(env_strings[this_one], '=');
  428.         if (equal_sign == (char *)NULL) 
  429.             ++len;
  430.         if (len - 1 > envfree)
  431.             ret = 2;
  432.         else {
  433.             if (iset_check_length(env_par, len) == 0) { 
  434.                 new_string = (char *) malloc (len);
  435.                 if (equal_sign == (char *)NULL) {
  436.                     strcpy(new_string, env_strings[this_one]);
  437.                     strcat(new_string, "=");
  438.                 }
  439.                 else {
  440.                     strncpy (new_string, env_strings[this_one], equal_sign - env_strings[this_one] + 1);
  441.                     new_string[equal_sign - env_strings[this_one] + 1] = '\0';
  442.                 }
  443.                 if (before) {
  444.                     strcat (new_string, env_value);
  445.                     strcat (new_string, ";");
  446.                     strcat (new_string, equal_sign + 1);
  447.                 }
  448.                 else    {
  449.                     if (strlen(equal_sign + 1) > 0) {
  450.                         strcat (new_string, equal_sign + 1);
  451.                         strcat (new_string, ";");
  452.                     }
  453.                     strcat (new_string, env_value);
  454.                 }
  455.  
  456.                 free (env_strings[this_one]);
  457.                 env_strings[this_one] = new_string;
  458.                 ret = 0;
  459.             } 
  460.             else
  461.                 ret = 1; 
  462.         }
  463.     }
  464.     else
  465.     {
  466.         /* simply set it */
  467.         len = strlen(env_par) + strlen(env_value) + 2;    /* = and nul */
  468.         if (len > envfree)
  469.             ret = 2;
  470.         else {
  471.             if (iset_check_length(env_par, strlen(env_value)) == 0) { 
  472.                 new_string = (char *)malloc (strlen(env_par) + strlen(env_value) + 2);
  473.                 if (env_value != NULL)
  474.                     sprintf(new_string, "%s=%s", strupr(env_par), env_value);
  475.                 else
  476.                     strcpy (new_string, strupr (env_par));
  477.                 env_strings[maxstring] = new_string;
  478.                 ++maxstring;
  479.                 env_strings[maxstring] = &terminating_null;
  480.                 ret = 0;
  481.             }
  482.             else
  483.                 ret = 1;
  484.         }
  485.     }
  486.  
  487.  
  488.  
  489.     if (ret == 0) {
  490.         /* rebuild environment block */
  491.         for (i = 0; i <= maxstring; i++) {
  492.             len = strlen (env_strings[i]) + 1; /* copy null byte */
  493.             _fmemcpy(envblock, (void _far *)env_strings[i], len);
  494.             envblock += len;
  495.         }
  496.  
  497.         *envblock = '\0';
  498.     }
  499.     iset_free_envstrings(env_strings);
  500.  
  501.     return ret;
  502. }
  503.  
  504.  
  505. int    iset_append_to_string_OLD (char *env_par, char *env_value)
  506. {
  507.     char        *env_strings[128];
  508.     char     *new_string;
  509.     BYTEPTR    envblock;
  510.     unsigned    envused;
  511.     unsigned    envfree;
  512.     int        maxstring;
  513.     int        i;
  514.     int        this_one;
  515.     int        len;
  516.     int        newlen;
  517.     int        ret;
  518.  
  519.     envblock = get_envblock();
  520.     maxstring = iset_load_envstrings (envblock, env_strings, &envused);
  521.     envfree = env_size(FP_SEG(envblock)) - envused;
  522.     if ((this_one = search_string(env_par, env_strings)) != -1)
  523.     {
  524. #ifdef ISETDEBUG
  525.         fprintf(stderr, "[D] Found existing %s\", env_strings[this_one]);
  526. #endif
  527.         /* append value to old string prefixing with a ; */
  528.         len = strlen (env_value) + 2;    /* ; and  nul */
  529.         if (len - 1 > envfree)
  530.             ret = 2;
  531.         else {
  532.             len+= strlen (env_strings[this_one]);
  533.             if (iset_check_length(env_par, len) == 0) { 
  534.                 new_string = (char *) malloc (len);
  535.                 strcpy (new_string, env_strings[this_one]);
  536.                 strcat (new_string, ";");
  537.                 strcat (new_string, env_value);
  538.                 free (env_strings[this_one]);
  539.                 env_strings[this_one] = new_string;
  540.                 ret = 0;
  541.             } 
  542.             else
  543.                 ret = 1; 
  544.         }
  545.     }
  546.     else
  547.     {
  548.         /* simply set it */
  549.         len = strlen(env_par) + strlen(env_value) + 2;    /* = and nul */
  550.         if (len > envfree)
  551.             ret = 2;
  552.         else {
  553.             if (iset_check_length(env_par, strlen(env_value)) == 0) { 
  554.                 new_string = (char *)malloc (strlen(env_par) + strlen(env_value) + 2);
  555.                 if (env_value != NULL)
  556.                     sprintf(new_string, "%s=%s", strupr(env_par), env_value);
  557.                 else
  558.                     strcpy (new_string, strupr (env_par));
  559.                 env_strings[maxstring] = new_string;
  560.                 ++maxstring;
  561.                 env_strings[maxstring] = &terminating_null;
  562.                 ret = 0;
  563.             }
  564.             else
  565.                 ret = 1;
  566.         }
  567.     }
  568.  
  569.  
  570.  
  571.     if (ret == 0) {
  572.         /* rebuild environment block */
  573.         for (i = 0; i <= maxstring; i++) {
  574.             len = strlen (env_strings[i]) + 1; /* copy null byte */
  575.             _fmemcpy(envblock, (void _far *)env_strings[i], len);
  576.             envblock += len;
  577.         }
  578.  
  579.         *envblock = '\0';
  580.     }
  581.     iset_free_envstrings(env_strings);
  582.  
  583.     return ret;
  584. }
  585.  
  586. int    iset_check_length(char *env_par, int len)
  587. {
  588.     /* special case: due to DOS limitations, and the PATH var
  589.        * can't exceed dos_max_pathvar_length(). So we have to test */
  590.     if (!stricmp(env_par, "PATH")) {
  591.         if (len > dos_max_pathvar_length()) {
  592.             fprintf(stderr, "%s: An environment variable cannot exceed 127 characters!\n", env_par);
  593.             return(1);
  594.         }
  595.     }
  596.     return (0);
  597. }
  598.  
  599. /* If the variable is not here, ignore.
  600.  * Else if there is no match with string_to_cut, ignore.
  601.  * Else take care of ";" contexts!
  602. */
  603. int iset_cut_string (char *env_par, char *string_to_cut)
  604. {
  605.     char    *env_strings[128];
  606.     char    *temp;
  607.     char *new_string;
  608.     char    *env_value;
  609.     char    *cutting_point;
  610.     char *next_piece;
  611.     char    *start_string;
  612.     char    *end_string;
  613.     BYTEPTR    envblock;
  614.     int    this_one;
  615.     int    i;
  616.     int    len;
  617.     int    maxstring;
  618.  
  619.     envblock = get_envblock();
  620.     maxstring = iset_load_envstrings (envblock, env_strings, NULL);
  621.     if ((this_one = search_string(env_par, env_strings)) != -1)
  622.     {
  623.         /* set value starting point */
  624.         if ((env_value = strchr(env_strings[this_one], '=')) != (char *)NULL) {
  625.             /* check match for string_to_cut */
  626.             /* take care: CASE SENSITIVE MATCH on value */
  627.             /* We must take care of ; context. */
  628.             if (strstr(++env_value, string_to_cut) != NULL) {
  629.                 temp = (char *)malloc(strlen(env_value + 1));
  630.                 start_string = env_value;
  631.                 do {
  632.                     if ((end_string = strchr(start_string, ';')) != (char *)NULL) {
  633.                         strncpy (temp, start_string, end_string - start_string);
  634.                         temp[end_string - start_string] = '\0';
  635.                     }
  636.                     else {
  637.                         strcpy (temp, start_string);
  638.                     }
  639.                     if (!strcmp(temp, string_to_cut)) {
  640.                         /* process cutting */
  641.                         strncpy (temp, env_value, start_string - env_value);
  642.                         temp[start_string - env_value]='\0';
  643.                         if (end_string != NULL)
  644.                             strcat (temp,++end_string);
  645.                         strcpy (env_value, temp);
  646.                         end_string = env_value + strlen(env_value) - 1;
  647.                         if (*end_string == ';')
  648.                             *end_string = '\0';
  649.                         break;    /* exit do...while */
  650.                     }
  651.                 } while (((start_string = end_string) != NULL) && ++start_string);
  652.                 free (temp);
  653.  
  654.             }
  655.          }    
  656.     }
  657.  
  658.  
  659.     for (i = 0; i <= maxstring; i++) {
  660.         /* don't copy string if orphaned (<var>= with no value) */
  661.         temp = env_strings[i];
  662.         if (temp[strlen(temp) - 1] != '=') {
  663.             len = strlen (env_strings[i]) + 1; /* copy null byte */
  664.             _fmemcpy(envblock, (void _far *)env_strings[i], len);
  665.             envblock += len;
  666.         }
  667.     }
  668.  
  669.     *envblock = '\0';
  670.     iset_free_envstrings(env_strings);
  671.  
  672.     return 0;
  673.         
  674.  
  675. }
  676.  
  677.     
  678.  
  679.  
  680. int iset_show_strings ()
  681. {
  682.     char *env_strings[128];
  683.     BYTEPTR    envblock;
  684.     unsigned    envsize;
  685.     unsigned    envused;
  686.     int    maxstring;
  687.     int    i;
  688.  
  689.     envblock = get_envblock();
  690.     maxstring = iset_load_envstrings (envblock, env_strings, &envused);
  691.     for (i = 0; i < maxstring; i++)
  692.         puts(env_strings[i]);
  693.     printf("********************************\n");
  694.     printf("Master environment at: %Fp\n", envblock);
  695.     printf("                 Size: %u\n", envsize = env_size(FP_SEG(envblock)));
  696.     printf("       No. of strings: %d\n", maxstring);
  697.     printf("           Bytes used: %u\n", envused);
  698.     printf("           Free space: %u\n", envsize - envused);
  699.     printf("********************************\n");
  700.  
  701.  
  702.  
  703.     iset_free_envstrings(env_strings);
  704.     return 0;
  705. }
  706.  
  707. #ifdef STANDALONE        
  708. main(int argc, char *argv[])
  709. {
  710.     POPTIONS    popt;
  711.     char        *s;
  712.  
  713.  
  714.     OPT_CREATE( popt, argc, argv );
  715.  
  716.     if (argc < 2 || Opt_IsSwitch (popt, 'h') || Opt_IsSwitch(popt, '?')) {
  717.         Syntax();
  718.         exit(-1);
  719.     }
  720.  
  721.     if (Opt_IsSwitch(popt, 'u')) {
  722.         if ((s = Opt_GetParameter (popt, 'u')) == NULL) {
  723.             Syntax();
  724.             exit(-1);
  725.         }
  726.         // delete string from environment 
  727.  
  728.         iset_delete_string (s);
  729.     }
  730.     else if (Opt_IsSwitch (popt, 's')) {
  731.         show_strings ();
  732.     }
  733.     else if (argc > 2)
  734.         iset_set_string (argv[1], argv[2]);
  735.     else 
  736.         iset_set_string (argv[1], NULL);
  737.  
  738.     return 0;
  739. }
  740.  
  741.  
  742. int Syntax ()
  743. {
  744.     puts ("I-Set " VERSIONE);
  745.     puts ("\tSintassi:     i-set <nomevar> [<valore>]");
  746.     puts ("\t              i-set [-u <nomevar>]");
  747.     puts ("\t              i-set -s");
  748.     puts ("\t              i-set -h │ -?");
  749.     puts ("\t-u (unset) elimina la variabile dalla tabella ambiente.");
  750.     puts ("\t-s (show) mostra il contenuto della tabella ambiente.");
  751.     puts ("\n (C) 1991 Shari, Inferentia S.r.l.");
  752.  
  753.     return 0;
  754. }
  755. #endif
  756.  
  757.  
  758.  
  759.  
  760.